package Huuuuugh;
import javax.sound.midi.*;
import javax.swing.*;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.List;
import java.io.*;
import java.util.PropertyResourceBundle;

public class MidiHandler
{
    static String settings;
    static File[] files = new File[88];
    static AudioClip[] sound = new AudioClip[88];
    static AudioClip chosenClip;
    static boolean isFileExi;
    static boolean isSetting;
    static boolean hasKey=false;
    static int key;
    static Frame frame = new Frame();
    static JLabel label = new JLabel();
    static JLabel label2 = new JLabel();
    static HashMap<Integer,Integer> keyS=new HashMap<>();
    public static void main(String[] args) throws IOException {
        File pro = new File(System.getProperty("user.dir")+"\\config.properties");
        if(!pro.exists()) {
            pro.createNewFile();
            FileWriter fr = new FileWriter(System.getProperty("user.dir")+"\\config.properties");
            fr.write("setting=true\n\n");
            fr.flush();
            fr.close();
        }
        InputStream in = new FileInputStream(pro);
        PropertyResourceBundle res = new PropertyResourceBundle(in);
        for (Object o : res.keySet().toArray()) {
            if(!((String) o).equals("setting")){
                keyS.put(Integer.parseInt((String) o),Integer.parseInt(res.getString((String) o)));//读取配置
            }
        }
        System.out.println(keyS.toString());
        frame.setLayout(new BorderLayout());
        frame.setBounds(10,10,750,130);
        frame.setTitle("请稍后，正在加载midi键盘...");
        frame.add("North",label);
        label.setFont(new Font(null, Font.BOLD,20));
        label.setText("请稍后，正在加载midi键盘...");
        label2.setFont(new Font(null, Font.BOLD,20));
        label2.setText("");
        frame.add("South",label2);
        frame.setVisible(true);
        if (res.getString("setting").equals("true")){
            System.out.println("配置模式");
            isSetting=true;

            frame.addWindowFocusListener(new WindowFocusListener() {
                @Override
                public void windowGainedFocus(WindowEvent e) {

                }

                @Override
                public void windowLostFocus(WindowEvent e) {
                    hasKey=false;
                }
            });
            frame.addKeyListener(new KeyListener() {
                @Override
                public void keyTyped(KeyEvent e) {

                }

                @Override
                public void keyPressed(KeyEvent e) {
                    hasKey=true;
                    label.setText("键盘上的按键"+e.getKeyCode());
                    key=e.getKeyCode();
                }

                @Override
                public void keyReleased(KeyEvent e) {
                    hasKey=false;
                    label2.setText("");
                }
            });
        }
        for (int i = 0; i < files.length; i++) {
            files[i] = new File(System.getProperty("user.dir") + "/piano_music/1 ("+(i+1)+").wav");
            try {
                sound[i] = Applet.newAudioClip(files[i].toURL());
                isFileExi=true;
            } catch(Exception e1){
                isFileExi=false;
            }

        }
        
        new MidiHandler();
    }

    public MidiHandler()
    {
        MidiDevice device;
        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
        for (int i = 0; i < infos.length; i++) {
            try {
                device = MidiSystem.getMidiDevice(infos[i]);
                //does the device have any transmitters?
                //if it does, add it to the device list
                System.out.println(infos[i]);

                //get all transmitters
                List<Transmitter> transmitters = device.getTransmitters();
                //and for each transmitter

                for(int j = 0; j<transmitters.size();j++) {
                    //create a new receiver
                    transmitters.get(j).setReceiver(
                            //using my own MidiInputReceiver
                            new MidiInputReceiver(device.getDeviceInfo().toString())
                    );
                }

                Transmitter trans = device.getTransmitter();
                trans.setReceiver(new MidiInputReceiver(device.getDeviceInfo().toString()));

                //open each device
                device.open();
                //if code gets this far without throwing an exception
                //print a success message
                System.out.println(device.getDeviceInfo()+" Was Opened");
                frame.setTitle("设置模式");
                label.setText("midi键盘加载成功");
                if(!isSetting){
                    frame.setVisible(false);
                }
            } catch (MidiUnavailableException e) {}
        }


    }

    /*
    * abacdefghijklmnopqrstuvwxyzvwxyzonmabcdefghijklmnohov xyzahovzahovzahoobilibilibilibilibiliaceacehjlo
    * */
    public class MidiInputReceiver implements Receiver{
        public int a = 1;
        public String name;
        public void updateData(int data){
            if(hasKey){
                keyS.put(data,key);
                System.out.println(data+"="+key);
                label2.setText("对应midi键盘上的"+data);
            }
        }
        public void bindKey(byte b){
            System.out.println("case " + b + ":");
            System.out.println("    r.keyPress(" + "KeyEvent.VK_NUMPAD" + a + ");");
            System.out.println("    break;");
            a++;
        }
        public MidiInputReceiver(String name) {
            this.name = name;
        }//-112按下
        //-128松开
        public void send(MidiMessage msg, long timeStamp) {
            //System.out.println("msg " + msg.getMessage()[1]);
            for (byte a:msg.getMessage()){
                //System.out.println(a);
            }
            if(isSetting){
                try {
                    FileWriter fr = new FileWriter(System.getProperty("user.dir")+"\\config.properties");
                    fr.write("setting=true\n\n");
                    for (Integer key : keyS.keySet()) {
                        fr.write(key+"="+keyS.get(key)+"\n");
                    }
                    fr.flush();
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            byte[] message = msg.getMessage();
            try {
                Robot r = new Robot();
                if(message[0] == -112){//按下
                    //System.out.println(message[1]);
                    Piano piano = new Piano(Integer.parseInt(message[1]+"")-9);
                    piano.start();

                    //bindKey(message[1]);

                    updateData(message[1]);

                    //System.out.println("press");
                    if(isSetting){
                        return;
                    }
                    try {
                        r.keyPress(keyS.get((int) message[1]));
                    }catch(Exception e){

                    }
                }
                if(message[0] == -128){//松开
                    //System.out.println("release");
                    if(isSetting){
                        return;
                    }
                    try {
                        r.keyRelease(keyS.get((int) message[1]));
                    }catch (Exception e){
                    }
                }
            } catch (AWTException e) {
                e.printStackTrace();
            }

        }
        public void close() {}


    }
}
class Piano extends Thread{
    int aaa;
    Piano(int qwq){
        aaa = qwq;
    }
    @Override
    public void run(){
        if(MidiHandler.isFileExi) {
            play(aaa);
        }
    }
    public void play(int i){
        stop(i);
        MidiHandler.chosenClip = MidiHandler.sound[i];
        MidiHandler.chosenClip.play();
    }
    public void stop(int i){
        MidiHandler.chosenClip = MidiHandler.sound[i];
        MidiHandler.chosenClip.stop();
    }
}